package org.myh.excel.concurrent;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.myh.excel.FieldSort;
import org.myh.excel.uitl.ClassUtil;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * ClassName: DivisibleExcelBuffer
 * Description: 多线程集成转换类的excelbuffer
 * date: 2024/3/23 14:37
 *
 * @author Yu Han
 * @since JDK 1.8
 */

public class MICClassDivisibleExcelBuffer extends AbstractDivisibleExcelBuffer<FieldSort> {


    private Class<? extends FieldSort> clazz;

    private ClassUtil<FieldSort> classUtil = new ClassUtil<>();

    public MICClassDivisibleExcelBuffer(InputStream inputStream, int bufferSize, int rowCacheSize, int sheetIndex, Class<? extends FieldSort> clazz) {
        super(inputStream, bufferSize, rowCacheSize, sheetIndex, (Class<FieldSort>) clazz);
    }

    /**
     * 读取excel表格，每rowCacheSize数装一次箱，多线程并发操作可以通过父类队列中获取数据
     *
     * @throws Exception
     * @Method hasNext() 判断是否还有数据，通过next()获取数据，每次从当前队列尾取一个值
     */
    @Override
    public void readExcel() throws Exception {
        // 1. 标记开始读取
        this.readState.set(READING);

        // 2. 通过反射先获取一个clazz实例，因反射效率较之new低，故使用此单实例clone方法获取对象，传入的对象需重写clone()
        FieldSort fieldSort = this.classUtil.newInstance(super.getClazz());
        // 2.1 获取排序好的字段名称
        String[] fields = fieldSort.sortField();
        // 2.2 获取回调
        ExcelDataCallBack callBack = getCallBack();

        System.out.println("读取共有：" + rowNum + "行");

        int rowIndex = 0;
        int cellIndex = 0;

        //3 声明存储rowCacheSize行的数据 map存储区间数据 rows存储行数据
        HashMap<Integer, List<FieldSort>> map = new HashMap<>(2);
        List<FieldSort> rows = new ArrayList<>(this.rowCacheSize);
        //4 循环遍历表格
        for (Row row : this.sheet) {
            // 4.1默认第一行不读取
            if (rowIndex++ == 0) {
                map.put(rowIndex, rows);
                continue;
            }


            if (row != null) {
                // 4.3  获取clone方法,通过clone获取对象，减少反射的损耗
                FieldSort cloneObj = fieldSort.clone();
                int fieldIndex = 0;
                // 4.4 获取第(i+1)行
                for (Cell cell : row) {
                    //获取单元格的内容，转成字符串
                    String stringCellValue = cell == null ? "" : cell.getStringCellValue();
                    //动态赋值
                    classUtil.setFieldByName(cloneObj, fields[fieldIndex++], stringCellValue);
                }

                if (callBack != null) {
                    callBack.sendRowData(rowIndex, cloneObj, rowNum,rowIndex != (this.rowNum - 1));
                }
                // 4.5 存入List
                rows.add(cloneObj);

                // 4.6 数据量达到，存入Deque
                if (rowIndex % rowCacheSize == 0) {
                    deque.addFirst(map);
                    // 5 重新初始化集合
                    map = new HashMap<>(2);
                    rows = new ArrayList<>(this.rowCacheSize);
                    map.put(rowIndex, rows);
                    readState.set(BE_DOING);
                }

                // 4.7 计算出最后一次数据的差值，存储最后一次数据
                if (rowIndex == (this.rowNum - 1)) {
                    System.out.println("最后一次插入:" + rowIndex);
                    deque.addFirst(map);
                    // 6.读取完成
                    readState.set(FINISHED);
                }
            }
        }
        closeResource();
    }


}


